-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[lldb] Fix StdUnorderedMapSynthProvider for GCC #164251
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[lldb] Fix StdUnorderedMapSynthProvider for GCC #164251
Conversation
|
@llvm/pr-subscribers-lldb Author: Sergei Druzhkov (DrSergei) ChangesThis patch adds small workaround for issue. It looks like code compiled with gcc has lack of some important debug information (e.g. DW_TAG_template_type_parameter for allocator). Example code: #include <unordered_map>
int main() {
std::unordered_map<int, int> map = {
{1, 2}
};
return 0;
}Output from GCC: Clang: I propose to add fallback implementation based on type of Full diff: https://github.com/llvm/llvm-project/pull/164251.diff 1 Files Affected:
diff --git a/lldb/examples/synthetic/gnu_libstdcpp.py b/lldb/examples/synthetic/gnu_libstdcpp.py
index f42a009c21f48..54d6248185fda 100644
--- a/lldb/examples/synthetic/gnu_libstdcpp.py
+++ b/lldb/examples/synthetic/gnu_libstdcpp.py
@@ -68,6 +68,11 @@ def extract_type(self):
template_arg_num = type.GetNumberOfTemplateArguments() - 1
allocator_type = type.GetTemplateArgumentType(template_arg_num)
data_type = allocator_type.GetTemplateArgumentType(0)
+ if data_type.IsValid():
+ return data_type
+ type = self.head.GetType()
+ head_type = type.GetTypedefedType().GetTypedefedType()
+ data_type = head_type.GetTemplateArgumentType(1)
return data_type
def update(self):
|
| if data_type.IsValid(): | ||
| return data_type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we just remove this codepath and use the same codepath for Clang and GCC? That way it's also going to be tested on CI.
| type = self.head.GetType() | ||
| head_type = type.GetTypedefedType().GetTypedefedType() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| type = self.head.GetType() | |
| head_type = type.GetTypedefedType().GetTypedefedType() | |
| head_type = self.head.GetType().GetCanonicalType() |
|
Can you file a bug on GCC about the missing template parameter? |
e63e7da to
efe6fbd
Compare
|
I am not sure that there is a reliable approach here so it may be better to have two ways to get data type. The current solution works both for gcc and clang on my laptop, but it might depend on the compiler version. I found an old review where mentioned that omitting certain fields can be an intentional debug info optimization. I suspect GCC developers may have the same intention. This bug was already submitted to GCC, but there has been no feedback. Failed AArch64 pipeline is not caused by this patch. It looks like there is a problem with infrastructure. |
That's a fair point. But just for testability, I think it's best if we use the same method of retrieval here. If Clang decides to omit those typedefs at some point then we can add another branch. But don't feel strongly about it
That is true, but I've only seen this apply to types or functions. First time I'm seeing this for other kinds of tags like
Good find. Interesting that this applies to |
|
Oh, yeah, GCC doesn't produce DW_TAG_template_type_parameter for unnamed template type parameters - yeah, it'd be a valid size optimization for them (relying on the uniqueness/identity of the DW_AT_name, I guess, for any type equivalence checking) - anything that can pull in more types into DWARF can be quite expensive (pulling in a whole type subgraph) so I could totally believe they did this for size optimization reasons. We (Clang/LLVM) don't put any DW_TAG_template_type_parameters on (non-defining) declarations of template entities - except on SCE and when using Simplified Template Names. But we do put them all on for definitions, whether or not they're named/used. |
Thanks for confirming! @DrSergei want me to merge this? |
Yes, thanks a lot |
This patch adds small workaround for [issue](llvm#152504). It looks like code compiled with gcc has lack of some important debug information (e.g. DW_TAG_template_type_parameter for allocator). Example code: ```cpp #include <unordered_map> int main() { std::unordered_map<int, int> map = { {1, 2} }; return 0; } ``` Output from `llvm-dwarfdump` for code compiled by GCC or Clang. I used system GCC (13.3.0) and Clang (18.1.3) on Ubuntu 24.04 (WSL). GCC: ``` 0x00001fcd: DW_TAG_class_type DW_AT_name ("allocator<std::pair<int const, int> >") DW_AT_byte_size (0x01) DW_AT_decl_file ("/usr/include/c++/13/bits/allocator.h") DW_AT_decl_line (130) DW_AT_decl_column (11) DW_AT_sibling (0x0000207c) 0x00001fda: DW_TAG_inheritance DW_AT_type (0x00001d0a "std::__new_allocator<std::pair<int const, int> >") DW_AT_data_member_location (0) DW_AT_accessibility (DW_ACCESS_public) 0x00001fe0: DW_TAG_subprogram DW_AT_external (true) DW_AT_name ("allocator") DW_AT_decl_file ("/usr/include/c++/13/bits/allocator.h") DW_AT_decl_line (163) DW_AT_decl_column (7) DW_AT_linkage_name ("_ZNSaISt4pairIKiiEEC4Ev") DW_AT_accessibility (DW_ACCESS_public) DW_AT_declaration (true) DW_AT_object_pointer (0x00001ff4) DW_AT_sibling (0x00001ffa) 0x00001ff4: DW_TAG_formal_parameter DW_AT_type (0x00004eb9 "std::allocator<std::pair<int const, int> > *") DW_AT_artificial (true) 0x00001ff9: NULL 0x00001ffa: DW_TAG_subprogram DW_AT_external (true) DW_AT_name ("allocator") DW_AT_decl_file ("/usr/include/c++/13/bits/allocator.h") DW_AT_decl_line (167) DW_AT_decl_column (7) DW_AT_linkage_name ("_ZNSaISt4pairIKiiEEC4ERKS2_") DW_AT_accessibility (DW_ACCESS_public) DW_AT_declaration (true) DW_AT_object_pointer (0x0000200e) DW_AT_sibling (0x00002019) 0x0000200e: DW_TAG_formal_parameter DW_AT_type (0x00004eb9 "std::allocator<std::pair<int const, int> > *") DW_AT_artificial (true) 0x00002013: DW_TAG_formal_parameter DW_AT_type (0x00004ec3 "const std::allocator<std::pair<int const, int> > &") 0x00002018: NULL 0x00002019: DW_TAG_subprogram DW_AT_external (true) DW_AT_name ("operator=") DW_AT_decl_file ("/usr/include/c++/13/bits/allocator.h") DW_AT_decl_line (172) DW_AT_decl_column (18) DW_AT_linkage_name ("_ZNSaISt4pairIKiiEEaSERKS2_") DW_AT_type (0x00004ec8 "std::allocator<std::pair<int const, int> > &") DW_AT_accessibility (DW_ACCESS_public) DW_AT_declaration (true) DW_AT_defaulted (DW_DEFAULTED_in_class) DW_AT_object_pointer (0x00002031) DW_AT_sibling (0x0000203c) 0x00002031: DW_TAG_formal_parameter DW_AT_type (0x00004eb9 "std::allocator<std::pair<int const, int> > *") DW_AT_artificial (true) 0x00002036: DW_TAG_formal_parameter DW_AT_type (0x00004ec3 "const std::allocator<std::pair<int const, int> > &") 0x0000203b: NULL 0x0000203c: DW_TAG_subprogram DW_AT_external (true) DW_AT_name ("~allocator") DW_AT_decl_file ("/usr/include/c++/13/bits/allocator.h") DW_AT_decl_line (184) DW_AT_decl_column (7) DW_AT_linkage_name ("_ZNSaISt4pairIKiiEED4Ev") DW_AT_accessibility (DW_ACCESS_public) DW_AT_declaration (true) DW_AT_object_pointer (0x00002050) DW_AT_sibling (0x0000205b) 0x00002050: DW_TAG_formal_parameter DW_AT_type (0x00004eb9 "std::allocator<std::pair<int const, int> > *") DW_AT_artificial (true) 0x00002055: DW_TAG_formal_parameter DW_AT_type (0x00004cab "int") DW_AT_artificial (true) 0x0000205a: NULL ``` Clang: ``` 0x00001a6e: DW_TAG_class_type DW_AT_calling_convention (DW_CC_pass_by_reference) DW_AT_name ("allocator<std::pair<const int, int> >") DW_AT_byte_size (0x01) DW_AT_decl_file ("/usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/allocator.h") DW_AT_decl_line (130) 0x00001a74: DW_TAG_template_type_parameter DW_AT_type (0x00000dec "std::pair<const int, int>") DW_AT_name ("_Tp") 0x00001a7a: DW_TAG_inheritance DW_AT_type (0x00001ad5 "std::__allocator_base<std::pair<const int, int> >") DW_AT_data_member_location (0x00) DW_AT_accessibility (DW_ACCESS_public) 0x00001a81: DW_TAG_subprogram DW_AT_name ("allocator") DW_AT_decl_file ("/usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/allocator.h") DW_AT_decl_line (163) DW_AT_declaration (true) DW_AT_external (true) DW_AT_accessibility (DW_ACCESS_public) 0x00001a86: DW_TAG_formal_parameter DW_AT_type (0x00002dd1 "std::allocator<std::pair<const int, int> > *") DW_AT_artificial (true) 0x00001a8b: NULL 0x00001a8c: DW_TAG_subprogram DW_AT_name ("allocator") DW_AT_decl_file ("/usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/allocator.h") DW_AT_decl_line (167) DW_AT_declaration (true) DW_AT_external (true) DW_AT_accessibility (DW_ACCESS_public) 0x00001a91: DW_TAG_formal_parameter DW_AT_type (0x00002dd1 "std::allocator<std::pair<const int, int> > *") DW_AT_artificial (true) 0x00001a96: DW_TAG_formal_parameter DW_AT_type (0x00002dd6 "const std::allocator<std::pair<const int, int> > &") 0x00001a9b: NULL 0x00001a9c: DW_TAG_subprogram DW_AT_linkage_name ("_ZNSaISt4pairIKiiEEaSERKS2_") DW_AT_name ("operator=") DW_AT_decl_file ("/usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/allocator.h") DW_AT_decl_line (172) DW_AT_type (0x00002de0 "std::allocator<std::pair<const int, int> > &") DW_AT_declaration (true) DW_AT_external (true) DW_AT_accessibility (DW_ACCESS_public) 0x00001aa6: DW_TAG_formal_parameter DW_AT_type (0x00002dd1 "std::allocator<std::pair<const int, int> > *") DW_AT_artificial (true) 0x00001aab: DW_TAG_formal_parameter DW_AT_type (0x00002dd6 "const std::allocator<std::pair<const int, int> > &") 0x00001ab0: NULL 0x00001ab1: DW_TAG_subprogram DW_AT_name ("~allocator") DW_AT_decl_file ("/usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/allocator.h") DW_AT_decl_line (184) DW_AT_declaration (true) DW_AT_external (true) DW_AT_accessibility (DW_ACCESS_public) 0x00001ab6: DW_TAG_formal_parameter DW_AT_type (0x00002dd1 "std::allocator<std::pair<const int, int> > *") DW_AT_artificial (true) 0x00001abb: NULL ``` I propose to add fallback implementation based on type of `_M_h`.
This patch adds small workaround for [issue](llvm#152504). It looks like code compiled with gcc has lack of some important debug information (e.g. DW_TAG_template_type_parameter for allocator). Example code: ```cpp #include <unordered_map> int main() { std::unordered_map<int, int> map = { {1, 2} }; return 0; } ``` Output from `llvm-dwarfdump` for code compiled by GCC or Clang. I used system GCC (13.3.0) and Clang (18.1.3) on Ubuntu 24.04 (WSL). GCC: ``` 0x00001fcd: DW_TAG_class_type DW_AT_name ("allocator<std::pair<int const, int> >") DW_AT_byte_size (0x01) DW_AT_decl_file ("/usr/include/c++/13/bits/allocator.h") DW_AT_decl_line (130) DW_AT_decl_column (11) DW_AT_sibling (0x0000207c) 0x00001fda: DW_TAG_inheritance DW_AT_type (0x00001d0a "std::__new_allocator<std::pair<int const, int> >") DW_AT_data_member_location (0) DW_AT_accessibility (DW_ACCESS_public) 0x00001fe0: DW_TAG_subprogram DW_AT_external (true) DW_AT_name ("allocator") DW_AT_decl_file ("/usr/include/c++/13/bits/allocator.h") DW_AT_decl_line (163) DW_AT_decl_column (7) DW_AT_linkage_name ("_ZNSaISt4pairIKiiEEC4Ev") DW_AT_accessibility (DW_ACCESS_public) DW_AT_declaration (true) DW_AT_object_pointer (0x00001ff4) DW_AT_sibling (0x00001ffa) 0x00001ff4: DW_TAG_formal_parameter DW_AT_type (0x00004eb9 "std::allocator<std::pair<int const, int> > *") DW_AT_artificial (true) 0x00001ff9: NULL 0x00001ffa: DW_TAG_subprogram DW_AT_external (true) DW_AT_name ("allocator") DW_AT_decl_file ("/usr/include/c++/13/bits/allocator.h") DW_AT_decl_line (167) DW_AT_decl_column (7) DW_AT_linkage_name ("_ZNSaISt4pairIKiiEEC4ERKS2_") DW_AT_accessibility (DW_ACCESS_public) DW_AT_declaration (true) DW_AT_object_pointer (0x0000200e) DW_AT_sibling (0x00002019) 0x0000200e: DW_TAG_formal_parameter DW_AT_type (0x00004eb9 "std::allocator<std::pair<int const, int> > *") DW_AT_artificial (true) 0x00002013: DW_TAG_formal_parameter DW_AT_type (0x00004ec3 "const std::allocator<std::pair<int const, int> > &") 0x00002018: NULL 0x00002019: DW_TAG_subprogram DW_AT_external (true) DW_AT_name ("operator=") DW_AT_decl_file ("/usr/include/c++/13/bits/allocator.h") DW_AT_decl_line (172) DW_AT_decl_column (18) DW_AT_linkage_name ("_ZNSaISt4pairIKiiEEaSERKS2_") DW_AT_type (0x00004ec8 "std::allocator<std::pair<int const, int> > &") DW_AT_accessibility (DW_ACCESS_public) DW_AT_declaration (true) DW_AT_defaulted (DW_DEFAULTED_in_class) DW_AT_object_pointer (0x00002031) DW_AT_sibling (0x0000203c) 0x00002031: DW_TAG_formal_parameter DW_AT_type (0x00004eb9 "std::allocator<std::pair<int const, int> > *") DW_AT_artificial (true) 0x00002036: DW_TAG_formal_parameter DW_AT_type (0x00004ec3 "const std::allocator<std::pair<int const, int> > &") 0x0000203b: NULL 0x0000203c: DW_TAG_subprogram DW_AT_external (true) DW_AT_name ("~allocator") DW_AT_decl_file ("/usr/include/c++/13/bits/allocator.h") DW_AT_decl_line (184) DW_AT_decl_column (7) DW_AT_linkage_name ("_ZNSaISt4pairIKiiEED4Ev") DW_AT_accessibility (DW_ACCESS_public) DW_AT_declaration (true) DW_AT_object_pointer (0x00002050) DW_AT_sibling (0x0000205b) 0x00002050: DW_TAG_formal_parameter DW_AT_type (0x00004eb9 "std::allocator<std::pair<int const, int> > *") DW_AT_artificial (true) 0x00002055: DW_TAG_formal_parameter DW_AT_type (0x00004cab "int") DW_AT_artificial (true) 0x0000205a: NULL ``` Clang: ``` 0x00001a6e: DW_TAG_class_type DW_AT_calling_convention (DW_CC_pass_by_reference) DW_AT_name ("allocator<std::pair<const int, int> >") DW_AT_byte_size (0x01) DW_AT_decl_file ("/usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/allocator.h") DW_AT_decl_line (130) 0x00001a74: DW_TAG_template_type_parameter DW_AT_type (0x00000dec "std::pair<const int, int>") DW_AT_name ("_Tp") 0x00001a7a: DW_TAG_inheritance DW_AT_type (0x00001ad5 "std::__allocator_base<std::pair<const int, int> >") DW_AT_data_member_location (0x00) DW_AT_accessibility (DW_ACCESS_public) 0x00001a81: DW_TAG_subprogram DW_AT_name ("allocator") DW_AT_decl_file ("/usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/allocator.h") DW_AT_decl_line (163) DW_AT_declaration (true) DW_AT_external (true) DW_AT_accessibility (DW_ACCESS_public) 0x00001a86: DW_TAG_formal_parameter DW_AT_type (0x00002dd1 "std::allocator<std::pair<const int, int> > *") DW_AT_artificial (true) 0x00001a8b: NULL 0x00001a8c: DW_TAG_subprogram DW_AT_name ("allocator") DW_AT_decl_file ("/usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/allocator.h") DW_AT_decl_line (167) DW_AT_declaration (true) DW_AT_external (true) DW_AT_accessibility (DW_ACCESS_public) 0x00001a91: DW_TAG_formal_parameter DW_AT_type (0x00002dd1 "std::allocator<std::pair<const int, int> > *") DW_AT_artificial (true) 0x00001a96: DW_TAG_formal_parameter DW_AT_type (0x00002dd6 "const std::allocator<std::pair<const int, int> > &") 0x00001a9b: NULL 0x00001a9c: DW_TAG_subprogram DW_AT_linkage_name ("_ZNSaISt4pairIKiiEEaSERKS2_") DW_AT_name ("operator=") DW_AT_decl_file ("/usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/allocator.h") DW_AT_decl_line (172) DW_AT_type (0x00002de0 "std::allocator<std::pair<const int, int> > &") DW_AT_declaration (true) DW_AT_external (true) DW_AT_accessibility (DW_ACCESS_public) 0x00001aa6: DW_TAG_formal_parameter DW_AT_type (0x00002dd1 "std::allocator<std::pair<const int, int> > *") DW_AT_artificial (true) 0x00001aab: DW_TAG_formal_parameter DW_AT_type (0x00002dd6 "const std::allocator<std::pair<const int, int> > &") 0x00001ab0: NULL 0x00001ab1: DW_TAG_subprogram DW_AT_name ("~allocator") DW_AT_decl_file ("/usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/allocator.h") DW_AT_decl_line (184) DW_AT_declaration (true) DW_AT_external (true) DW_AT_accessibility (DW_ACCESS_public) 0x00001ab6: DW_TAG_formal_parameter DW_AT_type (0x00002dd1 "std::allocator<std::pair<const int, int> > *") DW_AT_artificial (true) 0x00001abb: NULL ``` I propose to add fallback implementation based on type of `_M_h`.
This patch adds small workaround for issue. It looks like code compiled with gcc has lack of some important debug information (e.g. DW_TAG_template_type_parameter for allocator).
Example code:
Output from
llvm-dwarfdumpfor code compiled by GCC or Clang. I used system GCC (13.3.0) and Clang (18.1.3) on Ubuntu 24.04 (WSL).GCC:
Clang:
I propose to add fallback implementation based on type of
_M_h.